//
// Created by QU on 24-9-21.
//

#ifndef INC_13TLV_ECHO_SERVER_H
#define INC_13TLV_ECHO_SERVER_H

#include <iostream>
#include <map>
#include <queue>
#include <print>
#include <optional>
#include <memory>
#include <mutex>

#include <boost/asio.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/random_generator.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/uuid_generators.hpp>

#include "MsgNode/Node.h"

using tcp = boost::asio::ip::tcp;
namespace ip = boost::asio::ip;
namespace asio = boost::asio;

class Session;
class Server;


template <typename T>
class Singleton
{
public:
    // delete copy method
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

    // Get Singleton Instance
    static std::shared_ptr<T> GetInstance()
    {
        static std::once_flag flag;
        std::call_once(flag, []()
        {
            m_instance_ptr = std::make_shared<T>();
        });
        return m_instance_ptr;
    }

protected:
    // 子类可以访问构造函数
    Singleton() = default;

    ~Singleton() = default;

    inline static std::shared_ptr<T> m_instance_ptr;
    // 静态成员变量初始化, 上面写inline了, 就不用在实现中初始化了. (C++17)
    // template <typename T>
    // std::shared_ptr<T> Singleton<T>::m_instance_ptr = nullptr;
};

typedef std::function<void (std::shared_ptr<Session>)> FuncCallBack;

class LogicSystem : public Singleton<LogicSystem>
{
    friend class Singleton<LogicSystem>;

private:
    LogicSystem() = default;
    ~LogicSystem() = default;
};


class Session : public std::enable_shared_from_this<Session>
{
public:
    static constexpr size_t MIN_BUFFER_SIZE = 20; // 初始缓冲区大小
    static constexpr size_t MAX_BUFFER_SIZE = 1024 * 1024; // 1MB
    static constexpr double EXPAND_THRESHOLD = 0.8; // 80%
    static constexpr double SHRINK_THRESHOLD = 0.2; // 20%
    static constexpr int SHRINK_DELAY = 10; // 延迟10次接收操作后才考虑收缩

    explicit Session(ip::tcp::socket&& socket, Server& server);
    ~Session();

    void StartSession();
    std::string GetUuid() const;

private:
    void StartAsyncRead();
    void ContinueRead();
    void HandleRead(const boost::system::error_code& ec, std::size_t bytes_transferred);
    static std::optional<Node> BufferProcessor(const std::vector<std::byte>& buffer, size_t buffer_size);
    bool AdjustBufferSize(size_t required_size = 0);

    void StartAsyncWrite(); // 开始异步发送
    void HandleWrite(const boost::system::error_code& ec, std::size_t bytes_transferred); // 处理异步发送的结果
    void SendNode(const std::shared_ptr<Node>& node);

    void HandleError(const boost::system::error_code& ec, const std::string& message = "") const;
    static std::ostream& PrintBuffer(std::ostream& os, const std::vector<std::byte>& buffer, size_t buffer_size,
                                     size_t header_size = Node::MAX_HEADER_SIZE);

    Server& m_server;
    tcp::socket m_socket;

    boost::uuids::uuid m_uuid;

    std::mutex m_send_mutex;
    std::queue<std::shared_ptr<Node>> m_send_queue;
    std::shared_ptr<Node> m_current_send_node;

    // std::unique_ptr<RecvNode> m_recv_node;

    std::vector<std::byte> m_recv_buffer;
    size_t m_recv_buffer_curr_len = 0;

    uint16_t m_temp_payload_size = 0;
    bool m_header_received_flag = false;

    int m_buffer_need_shrink_counter = 0;
};


class Server
{
public:
    explicit Server(boost::asio::io_context& io_context, int16_t port);
    ~Server();
    static void PrintRemoteSockInformation(const ip::tcp::socket& sock);

    void ClearSession(const std::string&);

private:
    void HandleAccept();

    asio::io_context& m_io_context;
    short m_port;
    tcp::acceptor m_acceptor;
    std::map<std::string, std::shared_ptr<Session>> m_sessions_map;

    std::shared_ptr<Session> m_current_session;
};

int main(int argc, char* argv[]);

#endif //INC_13TLV_ECHO_SERVER_H
